<?php
/**
 * 测试积分计算逻辑
 */

// 模拟积分计算函数
function calculatePoints(int $durationMinutes, string $startTime, string $endTime, int $unitMinutes, string $rounding, string $timeSlotsJson): int
{
    // 如果有时间段配置，优先使用时间段规则
    if (!empty($timeSlotsJson)) {
        $timeSlots = json_decode($timeSlotsJson, true);
        if (is_array($timeSlots) && count($timeSlots) > 0) {
            return calculatePointsByTimeSlots($durationMinutes, $startTime, $endTime, $timeSlots, $unitMinutes, $rounding);
        }
    }

    // 使用基础规则：每满N分钟记1分
    if ($unitMinutes <= 0) $unitMinutes = 10;

    $rawPoints = $durationMinutes / $unitMinutes;

    // 根据取整方式计算
    switch ($rounding) {
        case 'ceil':
            return intval(ceil($rawPoints));
        case 'round':
            return intval(round($rawPoints));
        case 'floor':
        default:
            return intval(floor($rawPoints));
    }
}

function calculatePointsByTimeSlots(int $durationMinutes, string $startTime, string $endTime, array $timeSlots, int $unitMinutes, string $rounding): int
{
    // 获取开始时间的小时和分钟
    $startHour = intval(date('H', strtotime($startTime)));
    $startMinute = intval(date('i', strtotime($startTime)));
    $startTimeValue = $startHour * 60 + $startMinute;

    $matchedSlot = null;

    // 查找开始时间所在的时间段
    foreach ($timeSlots as $slot) {
        $slotStart = $slot['start'] ?? '';
        $slotEnd = $slot['end'] ?? '';
        $slotPoints = floatval($slot['points_per_hour'] ?? 0);

        if (empty($slotStart) || empty($slotEnd)) continue;

        list($sh, $sm) = explode(':', $slotStart);
        list($eh, $em) = explode(':', $slotEnd);

        $slotStartValue = intval($sh) * 60 + intval($sm);
        $slotEndValue = intval($eh) * 60 + intval($em);

        // 判断开始时间是否在该时间段内
        if ($slotStartValue <= $slotEndValue) {
            // 正常时间段
            if ($startTimeValue >= $slotStartValue && $startTimeValue < $slotEndValue) {
                $matchedSlot = $slot;
                break;
            }
        } else {
            // 跨午夜时间段
            if ($startTimeValue >= $slotStartValue || $startTimeValue < $slotEndValue) {
                $matchedSlot = $slot;
                break;
            }
        }
    }

    // 如果找到匹配的时间段，使用时间段规则
    if ($matchedSlot !== null) {
        $pointsPerHour = floatval($matchedSlot['points_per_hour'] ?? 1);
        $durationHours = $durationMinutes / 60.0;
        $rawPoints = $durationHours * $pointsPerHour;
        echo "  ✅ 匹配时间段: {$matchedSlot['start']}-{$matchedSlot['end']}, {$pointsPerHour} 积分/小时\n";
        echo "  📊 计算: {$durationMinutes} 分钟 = {$durationHours} 小时 × {$pointsPerHour} = {$rawPoints}\n";
    } else {
        // 使用基础规则
        if ($unitMinutes <= 0) $unitMinutes = 10;
        $rawPoints = $durationMinutes / $unitMinutes;
        echo "  ⚠️  未匹配任何时间段，使用基础规则\n";
        echo "  📊 计算: {$durationMinutes} 分钟 / {$unitMinutes} = {$rawPoints}\n";
    }

    // 根据取整方式计算
    switch ($rounding) {
        case 'ceil':
            return intval(ceil($rawPoints));
        case 'round':
            return intval(round($rawPoints));
        case 'floor':
        default:
            return intval(floor($rawPoints));
    }
}

echo "=== 积分计算逻辑测试 ===\n\n";

// 测试配置
$unitMinutes = 3; // 基础规则：每3分钟1分
$rounding = 'floor'; // 向下取整
$timeSlots = [
    ["start" => "12:00", "end" => "15:00", "points_per_hour" => 1],
    ["start" => "15:00", "end" => "20:00", "points_per_hour" => 2]
];
$timeSlotsJson = json_encode($timeSlots);

echo "【配置】\n";
echo "基础规则: 每 {$unitMinutes} 分钟记 1 分\n";
echo "取整方式: {$rounding}\n";
echo "时间段规则:\n";
foreach ($timeSlots as $slot) {
    echo "  - {$slot['start']} - {$slot['end']}: {$slot['points_per_hour']} 积分/小时\n";
}
echo "\n";

// 测试用例
$testCases = [
    // 在时间段内的测试
    ["start" => "2025-10-14 12:30:00", "end" => "2025-10-14 13:00:00", "desc" => "在12:00-15:00时间段内，签到30分钟"],
    ["start" => "2025-10-14 13:00:00", "end" => "2025-10-14 14:00:00", "desc" => "在12:00-15:00时间段内，签到60分钟"],
    ["start" => "2025-10-14 15:30:00", "end" => "2025-10-14 16:30:00", "desc" => "在15:00-20:00时间段内，签到60分钟"],
    ["start" => "2025-10-14 16:00:00", "end" => "2025-10-14 17:30:00", "desc" => "在15:00-20:00时间段内，签到90分钟"],
    
    // 不在时间段内的测试
    ["start" => "2025-10-14 08:00:00", "end" => "2025-10-14 08:30:00", "desc" => "不在任何时间段内（早上8点），签到30分钟"],
    ["start" => "2025-10-14 21:00:00", "end" => "2025-10-14 21:30:00", "desc" => "不在任何时间段内（晚上9点），签到30分钟"],
    ["start" => "2025-10-14 10:00:00", "end" => "2025-10-14 10:10:00", "desc" => "不在任何时间段内（早上10点），签到10分钟"],
];

echo "【测试用例】\n\n";

foreach ($testCases as $index => $case) {
    $startTime = $case['start'];
    $endTime = $case['end'];
    $desc = $case['desc'];
    
    $startTs = strtotime($startTime);
    $endTs = strtotime($endTime);
    $durationMinutes = intval(($endTs - $startTs) / 60);
    
    echo "测试 " . ($index + 1) . ": {$desc}\n";
    echo "  开始时间: " . date('H:i', $startTs) . "\n";
    echo "  结束时间: " . date('H:i', $endTs) . "\n";
    echo "  时长: {$durationMinutes} 分钟\n";
    
    $points = calculatePoints($durationMinutes, $startTime, $endTime, $unitMinutes, $rounding, $timeSlotsJson);
    
    echo "  🎯 最终积分: {$points} 分\n";
    echo "\n";
}

echo "=== 测试完成 ===\n";

